﻿using System;
using System.Text;
using System.Collections.Generic;
using System.Linq;
using SWS = System.Web.Security;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using CodeCamp.EFDAL;
using CodeCamp.Model;
using CCC = CodeCamp.Controllers;

namespace CodeCamp.Tests.DataUpdateTests
{
    [TestClass]
    public class SiteUserUpdates : TestBase
    {
#if false
        [TestMethod]
        public void AddSiteUsersForExistingPresenterUsers()
        {
            string rawEventsToUpdate = GetAppSettingString("eventsToUpdate");
            string[] eventsToUpdate = rawEventsToUpdate.Split(',');

            using (CodeCampDbContext dc = new CodeCampDbContext())
            {
                var events = dc.Events.OrderBy(e => e.DisplaySortOrder).ToList();

                var presenterRole = dc.Roles4Events.Where(r => r.RoleName == CodeCamp.Models.Shared.CCRoles.RoleNames.Presenter).FirstOrDefault();
                if (presenterRole == null)
                {
                    Role4Event pr = new Role4Event { RoleName = CodeCamp.Models.Shared.CCRoles.RoleNames.Presenter };
                    dc.Roles4Events.Add(pr);
                    dc.SaveChanges();
                    presenterRole = pr;
                }

                foreach (var ev in events)
                {
                    if (!eventsToUpdate.Contains(ev.ShortName))
                    {
                        TestContext.WriteLine("{0} -- Not processing presenters.", ev.ShortName);
                    }
                    else
                    {
                        int updateCount = 0;
                        TestContext.WriteLine("{0} -- Processing presenters.", ev.ShortName);

                        var presenters = ev.Presenters
                                            .Where(p => p.SiteUserId == null)
                                            .Where(p2 => p2.UserIdentityIssuer == CCC.CodeCampDataRepository.IdentityIssuers.CodeCamp)
                                            .Where(p2 => p2.UserIdentityProvider == CCC.CodeCampDataRepository.IdentityProviders.CodeCamp)
                                            .ToList();
                        foreach (var pr in presenters)
                        {
                            TestContext.WriteLine("{1}\t{2} {3}\t{4}{0}\t{5}{0}\t{6}{0}\t{7}{0}\t{8}{0}",
                                Environment.NewLine,
                                pr.Id,
                                pr.FirstName,
                                pr.LastName,
                                pr.EmailAddress,
                                pr.UserIdentityProvider,
                                pr.UserIdentityIssuer,
                                pr.UserIdentityClaimType,
                                pr.UserIdentityClaim);

                            SiteUser siteUser = new SiteUser
                            {
                                CreatedBy = "AddSiteUserProcess",
                                EmailAddress = pr.EmailAddress,
                                FirstName = pr.FirstName,
                                IsApproved = true,
                                IsLockedOut = false,
                                LastName = pr.LastName,
                                UserClaimEmailAddress = pr.UserClaimEmailAddress,
                                UserIdentityClaim = pr.UserIdentityClaim,
                                UserIdentityClaimType = pr.UserIdentityClaimType,
                                UserIdentityIssuer = pr.UserIdentityIssuer,
                                UserIdentityProvider = pr.UserIdentityProvider
                            };
                            dc.SiteUsers.Add(siteUser);
                            dc.SaveChanges();
                            pr.SiteUserId = siteUser.Id;
                            pr.SiteUser = siteUser;
                            dc.SaveChanges();
                            UserInEventRole uier = new UserInEventRole
                            {
                                CreatedBy = "AddSiteUserProcess",
                                Event = ev,
                                EventId = ev.Id,
                                Role4Event = presenterRole,
                                Role4EventId = presenterRole.Id,
                                SiteUser = siteUser,
                                SiteUserId = siteUser.Id
                            };
                            dc.UsersInEventRoles.Add(uier);
                            dc.SaveChanges();
                            updateCount++;
                        }
                        TestContext.WriteLine("Created {0} SiteUsers for {1}.", updateCount, ev.ShortName);
                    }
                }
            }
        }

        [TestMethod]
        public void AddSiteUsersForExistingNonPresenterUsers()
        {
            SWS.MembershipProvider memProvider = SWS.Membership.Provider;
            Assert.IsNotNull(memProvider);
            Assert.AreEqual("CodeCampTest", memProvider.ApplicationName);
            SWS.RoleProvider roleProvider = SWS.Roles.Provider;
            Assert.IsNotNull(roleProvider);
            Assert.AreEqual("CodeCampTest", roleProvider.ApplicationName);

            int pageIndex = 0;
            int pageSize = 100;
            int totalRecords;
            SWS.MembershipUserCollection users = SWS.Membership.GetAllUsers(pageIndex, pageSize, out totalRecords);

            using (CodeCampDbContext dc = new CodeCampDbContext())
            {
                var bigCheezeRole = dc.Roles.Where(r => r.RoleName == CodeCamp.Models.Shared.CCRoles.RoleNames.BigCheeze).FirstOrDefault();
                if (bigCheezeRole == null)
                {
                    Role bcr = new Role { RoleName = CodeCamp.Models.Shared.CCRoles.RoleNames.BigCheeze };
                    dc.Roles.Add(bcr);
                    dc.SaveChanges();
                    bigCheezeRole = bcr;
                }

                foreach (SWS.MembershipUser user in users)
                {
                    var presenters = dc.Presenters
                                        .Where(p => p.UserIdentityClaim == user.UserName)
                                            .Where(p2 => p2.UserIdentityIssuer == CCC.CodeCampDataRepository.IdentityIssuers.CodeCamp)
                                            .Where(p2 => p2.UserIdentityProvider == CCC.CodeCampDataRepository.IdentityProviders.CodeCamp)
                                            .ToList();

                    string[] usersInBigCheeze = roleProvider.GetUsersInRole(CodeCamp.Models.Shared.CCRoles.RoleNames.BigCheeze);

                    SiteUser siteUser = null;
                    if (presenters.Count() == 0)
                    {
                        TestContext.WriteLine("User \"{0}\" presenter count = {1}", user.UserName, presenters.Count());
                        siteUser = new SiteUser
                        {
                            CreatedBy = "AddSiteUserProcess",
                            EmailAddress = user.Email,
                            FirstName = user.UserName,
                            IsApproved = true,
                            IsLockedOut = false,
                            LastName = "?",
                            UserClaimEmailAddress = user.Email,
                            UserIdentityClaim = user.UserName,
                            UserIdentityClaimType = CCC.CodeCampDataRepository.ClaimTypes.username,
                            UserIdentityIssuer = CCC.CodeCampDataRepository.IdentityIssuers.CodeCamp,
                            UserIdentityProvider = CCC.CodeCampDataRepository.IdentityProviders.CodeCamp
                        };
                        dc.SiteUsers.Add(siteUser);
                        dc.SaveChanges();
                    }
                    else
                    {
                        siteUser = dc.SiteUsers
                                    .Where(su => su.UserIdentityClaim == user.UserName)
                                    .Where(su => su.UserIdentityIssuer == CCC.CodeCampDataRepository.IdentityIssuers.CodeCamp)
                                    .Where(su => su.UserIdentityProvider == CCC.CodeCampDataRepository.IdentityProviders.CodeCamp)
                                    .FirstOrDefault();
                    }
                    if (usersInBigCheeze.Contains(user.UserName))
                    {
                        TestContext.WriteLine("User \"{0}\" is {1}", user.UserName, CodeCamp.Models.Shared.CCRoles.RoleNames.BigCheeze);
                        if (siteUser == null)
                        {
                            TestContext.WriteLine("No SiteUser for user \"{0}\".", user.UserName);
                        }
                        else
                        {
                            UserInRole uir = new UserInRole
                            {
                                CreatedBy = "AddSiteUserProcess",
                                Role = bigCheezeRole,
                                RoleId = bigCheezeRole.Id,
                                SiteUser = siteUser,
                                SiteUserId = siteUser.Id
                            };
                            dc.UsersInRoles.Add(uir);
                            dc.SaveChanges();
                        }
                    }
                }
            }
        }
#endif


        [TestMethod]
        public void UpdateSiteUsersForAdditionalRoles()
        {
            SWS.MembershipProvider memProvider = SWS.Membership.Provider;
            Assert.IsNotNull(memProvider);
            Assert.AreEqual("CodeCampTest", memProvider.ApplicationName);
            SWS.RoleProvider roleProvider = SWS.Roles.Provider;
            Assert.IsNotNull(roleProvider);
            Assert.AreEqual("CodeCampTest", roleProvider.ApplicationName);

            string rawEventsToUpdate = GetAppSettingString("eventsToUpdate");
            string[] eventsToUpdate = rawEventsToUpdate.Split(',');

            using (CodeCampDbContext dc = new CodeCampDbContext())
            {
                var events = dc.Events.OrderBy(e => e.DisplaySortOrder).ToList();
                foreach (var ev in events)
                {
                    if (string.IsNullOrWhiteSpace(ev.NonPublicEventPreviewRole))
                    {
                        TestContext.WriteLine("Event \"{0}\" has no NonPublicEventPreviewRole.", ev.ShortName);
                    }
                    else
                    {
                        TestContext.WriteLine("Event \"{0}\" NonPublicEventPreviewRole = \"{1}\".", ev.ShortName, ev.NonPublicEventPreviewRole);

                        if (!eventsToUpdate.Contains(ev.ShortName))
                        {
                            TestContext.WriteLine("Event {0} -- Not processing NonPublicEventPreviewRole.", ev.ShortName);
                        }
                        else
                        {
                            string[] mproles = roleProvider.GetAllRoles();

                            if ((mproles == null) || !mproles.Contains(ev.NonPublicEventPreviewRole))
                            {
                                TestContext.WriteLine("Event \"{0}\" NonPublicEventPreviewRole = \"{1}\" - no such role in role provider.", ev.ShortName, ev.NonPublicEventPreviewRole);
                            }
                            else
                            {
                                var nonPublicEventPreviewRole = dc.Roles4Events.Where(r => r.RoleName == ev.NonPublicEventPreviewRole).FirstOrDefault();
                                if (nonPublicEventPreviewRole == null)
                                {
                                    TestContext.WriteLine("CodeCamp role \"{0}\" does not exist.", ev.NonPublicEventPreviewRole);
                                    Role4Event role = new Role4Event
                                    {
                                        RoleName = ev.NonPublicEventPreviewRole
                                    };
                                    dc.Roles4Events.Add(role);
                                    dc.SaveChanges();
                                    nonPublicEventPreviewRole = role;
                                }

                                string[] usersInNPEPR = roleProvider.GetUsersInRole(ev.NonPublicEventPreviewRole);
                                if ((usersInNPEPR == null) || (usersInNPEPR.Length == 0))
                                {
                                    TestContext.WriteLine("no users in role \"{0}\".", ev.NonPublicEventPreviewRole);
                                }
                                else
                                {
                                    TestContext.WriteLine("{0} user(s) in role \"{1}\".", usersInNPEPR.Length, ev.NonPublicEventPreviewRole);
                                    int updateCount = 0;
                                    foreach (string musername in usersInNPEPR)
                                    {
                                        var siteUser = dc.SiteUsers
                                                        .Where(su => su.UserIdentityIssuer == CCC.CodeCampDataRepository.IdentityIssuers.CodeCamp)
                                                        .Where(su => su.UserIdentityProvider == CCC.CodeCampDataRepository.IdentityProviders.CodeCamp)
                                                        .Where(su => su.UserIdentityClaimType == CCC.CodeCampDataRepository.ClaimTypes.username)
                                                        .Where(su => su.UserIdentityClaim == musername)
                                                        .FirstOrDefault();

                                        if (siteUser == null)
                                        {
                                            TestContext.WriteLine("SiteUser \"{0}\" not found.", musername);
                                        }
                                        else
                                        {
                                            TestContext.WriteLine("SiteUser \"{0}\" found.", musername);
                                            var userInEventRole = dc.UsersInEventRoles
                                                                    .Where(ur => ur.EventId == ev.Id)
                                                                    .Where(ur => ur.SiteUserId == siteUser.Id)
                                                                    .Where(ur => ur.Role4EventId == nonPublicEventPreviewRole.Id)
                                                                    .FirstOrDefault();

                                            if (userInEventRole != null)
                                            {
                                                TestContext.WriteLine("SiteUser {0} \"{1}\" in role {2} \"{3}\" created {4:yyyy-MM-dd  HH:mm:ss.fff} (UTC) by {5}.", 
                                                    userInEventRole.SiteUserId,
                                                    userInEventRole.SiteUser.UserIdentityClaim,
                                                    userInEventRole.Role4EventId,
                                                    userInEventRole.Role4Event.RoleName,
                                                    userInEventRole.CreatedUTC,
                                                    userInEventRole.CreatedBy);
                                            }
                                            else
                                            {
                                                UserInEventRole uier = new UserInEventRole
                                                {
                                                    CreatedBy = "UpdateSiteUserProcess",
                                                    Event = ev,
                                                    EventId = ev.Id,
                                                    Role4Event = nonPublicEventPreviewRole,
                                                    Role4EventId = nonPublicEventPreviewRole.Id,
                                                    SiteUser = siteUser,
                                                    SiteUserId = siteUser.Id
                                                };
                                                dc.UsersInEventRoles.Add(uier);
                                                dc.SaveChanges();
                                                updateCount++;
                                            }
                                        }
                                    }
                                    TestContext.WriteLine("Updated {0} users.", updateCount);
                                }
                            }
                        }
                    }
                }
            }
        }

#if false
        [TestMethod]
        public void ConnectSiteUserAndPresenter()
        {
            string rawEventsToUpdate = GetAppSettingString("eventsToUpdate");
            string[] eventsToUpdate = rawEventsToUpdate.Split(',');

            using (CodeCampDbContext dc = new CodeCampDbContext())
            {
                var events = dc.Events.OrderBy(e => e.DisplaySortOrder).ToList();
                foreach (var ev in events)
                {
                    TestContext.WriteLine("");
                    if (!eventsToUpdate.Contains(ev.ShortName))
                    {
                        TestContext.WriteLine("{0} -- Not processing presenters.", ev.ShortName);
                    }
                    else
                    {
                        int updateCount = 0;
                        TestContext.WriteLine("{0} -- Processing presenters.", ev.ShortName);

                        foreach (var pr in ev.Presenters
                                        .Where(p => p.UserIdentityIssuer == CCC.CodeCampDataRepository.IdentityIssuers.CodeCamp)
                                        .Where(p => p.UserIdentityProvider == CCC.CodeCampDataRepository.IdentityProviders.CodeCamp)
                                        .Where(p => p.UserIdentityClaimType == CCC.CodeCampDataRepository.ClaimTypes.username)
                                )
                        {
                            if (pr.SiteUserId.HasValue)
                            {
                                TestContext.WriteLine("Presenter \"{0}\" - pr.SiteUserId={1} has site user.", pr.UserIdentityClaim, pr.SiteUserId);
                            }
                            else
                            {
                                var siteUser = dc.SiteUsers
                                        .Where(su => su.UserIdentityIssuer == CCC.CodeCampDataRepository.IdentityIssuers.CodeCamp)
                                        .Where(su => su.UserIdentityProvider == CCC.CodeCampDataRepository.IdentityProviders.CodeCamp)
                                        .Where(su => su.UserIdentityClaimType == CCC.CodeCampDataRepository.ClaimTypes.username)
                                        .Where(su => su.UserIdentityClaim == pr.UserIdentityClaim).FirstOrDefault();

                                if (siteUser == null)
                                {
                                    TestContext.WriteLine("Presenter \"{0}\" - pr.SiteUserId={1} -- could not find Site User", pr.UserIdentityClaim, pr.SiteUserId);
                                }
                                else
                                {
                                    TestContext.WriteLine("Presenter \"{0}\" - pr.SiteUserId={1} -- siteUser \"{2}\", id={3}",
                                        pr.UserIdentityClaim, pr.SiteUserId,
                                        siteUser.UserIdentityClaim, siteUser.Id);
                                }
                            }
                        }
                    }
                }
            }
        }
#endif

    }
}
